<template>
  <div class="merge-table" v-bind="$attrs" v-on="$listeners">
    <table class="table table-bordered">
      <tbody>
        <tr v-for="(row, index) in rows" :key="index">
          <td
            v-for="(td, idx) in row"
            :key="idx"
            :colspan="td.colSpan"
            :rowspan="td.rowSpan"
          >
            <slot
              name="td"
              v-bind="{row, rowIdx: index, td, tdIdx: idx}"
            ></slot>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import Tree from './util/Tree'
import {debounce} from 'lodash'
import {v4 as uuidv4} from 'uuid'
/**
 * 合并表格组件
 * 专注于树结构与合并表格之间的转换
 * @example ./MergeTable.md
 * @displayName MergeTable
 */
export default {
  name: 'MergeTable',
  model: {
    prop: 'treeData',
    event: 'update'
  },
  props: {
    /**
     * 树数据，以children为子节点属性名，id为索引
     * @model
     */
    treeData: {
      type: Object,
      required: true,
      default: () => ({})
    }
  },
  data() {
    return {
      rows: []
    }
  },
  watch: {
    treeData: {
      deep: true,
      handler() {
        this.compile()
      }
    }
  },
  mounted() {
    this.compile()
  },
  methods: {
    /**
     * 根据id获取节点数据
     * @param {string | Number} nodeId
     * @public
     */
    GetNodeById(nodeId) {
      return Tree.getNodeById(this.treeData, nodeId)
    },
    /**
     * 根据id获取父节点数据
     * @param {string | Number} nodeId
     * @public
     */
    GetParentByChildId(nodeId) {
      return Tree.getParentByChildId(this.treeData, nodeId, this.treeData)
    },
    /**
     * 删除某节点
     * @param {string | Number} nodeId
     * @public
     */
    RemoveNode(nodeId) {
      const parent = Tree.getParentByChildId(
        this.treeData,
        nodeId,
        this.treeData
      )
      const index = parent.children.findIndex(item => item.id === nodeId)
      parent.children.splice(index, 1)
      this.$emit('update', this.treeData)
    },
    /**
     * 往id下添加一个子节点
     * @param {string | Number} nodeId
     * @param {Object} value
     * @public
     */
    AddChild(nodeId, value = {}) {
      const parent = Tree.getNodeById(this.treeData, nodeId)

      const children = parent.children || []
      const id = uuidv4()

      children.push({
        id,
        parentId: nodeId,
        ...value
      })
      this.$set(parent, 'children', children)
    },
    /**
     * 转换tree转换后的数组
     * @public
     */
    GetRows() {
      return this.rows
    },
    /**
     * 改变节点数据
     * @param {string | Number} key 节点属性
     * @param {Object} value 节点值
     * @param {string | Number} nodeId 节点id
     * @public
     */
    ChangeNode(key, value, nodeId) {
      const data = Tree.getNodeById(this.treeData, nodeId)
      this.$set(data, key, value)
    },

    compile: debounce(function() {
      const rows = Tree.translate2Rows(this.treeData)
      this.rows = rows
    }, 50)
  }
}
</script>

<style lang="less" scoped>
.merge-table {
  table {
    border-spacing: 0;
    border-collapse: collapse;
  }

  td {
    border: 1px solid;
  }

  .table-bordered > thead > tr > th,
  .table-bordered > tbody > tr > th,
  .table-bordered > tfoot > tr > th,
  .table-bordered > thead > tr > td,
  .table-bordered > tbody > tr > td,
  .table-bordered > tfoot > tr > td {
    border-color: #d2d6de;
  }
}
</style>
